package config

import (
	"encoding/json"
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"io"
	"net/http"
)

var GlobalMap = map[string]string{
	"mysql": "%s:%s@tcp(%s:%d)/mysql?charset=utf8mb4&parseTime=True&loc=Local",
}

var DbInstanceMap = map[int]*ConnetInfo{}
var dbIndexer = 0

type ConnetInfo struct {
	DbType string
	id     int
	Conn   *gorm.DB
}

func (conf *ConnetInfo) PutInGlobal() {
	var index = dbIndexer + 1
	conf.id = index
	DbInstanceMap[index] = conf
}

type IDbConnect interface {
	Connect() bool
	ShowTables() string
	ShowDatabase() string
	DbInfo() DbConfig
}

type DbConfig struct {
	DbId     int    `json:"db_id"`
	DbType   string `json:"db_type"`
	Host     string `json:"host"`
	Port     int    `json:"port"`
	Username string `json:"username"`
	Password string `json:"password"`
	Url      string `json:"url"`
}

func (conf *DbConfig) MakeConnInstance() IDbConnect {
	if conf.DbType == "mysql" {
		return &MysqlDbConnect{
			conf: conf,
		}
	}
	if conf.DbType == "sqlite" {
		return &Sqlite3DbConnect{}
	}
	return nil
}

type DbConfigFactory struct {
	R *http.Request
}

func (d *DbConfigFactory) MakeConfig() DbConfig {
	var bytes, _ = io.ReadAll(d.R.Body)
	var s = string(bytes)
	var dbC = DbConfig{}
	err := json.Unmarshal([]byte(s), &dbC)
	if err != nil {
		return DbConfig{}
	}
	return dbC
}

type DbTypeConfig struct {
	dns     string
	db_type string
}

type MysqlDbConnect struct {
	conf *DbConfig
}

func (conf *MysqlDbConnect) Connect() bool {
	var info = conf.DbInfo()
	dsn := fmt.Sprintf(
		"%s:%s@tcp(%s:%d)/mysql?charset=utf8mb4&parseTime=True&loc=Local",
		info.Username,
		info.Password,
		info.Host,
		info.Port,
	)

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		fmt.Println("Failed to connect to database:", err)
		return false
	}
	var sss = &ConnetInfo{
		DbType: info.DbType,
		Conn:   db,
	}
	sss.PutInGlobal()
	return true
}

func (conf *MysqlDbConnect) ShowTables() string {
	//查询所有表名
	var tables []string
	db := DbInstanceMap[conf.conf.DbId].Conn

	result := db.Raw("SHOW TABLES").Scan(&tables)
	if result.Error != nil {
		fmt.Println("Failed to connect to database:", result.Error)
	}
	fmt.Println("Connected to database:", tables)
	return "show tables"
}

func (conf *MysqlDbConnect) ShowDatabase() string {
	return "show databases"
}
func (conf *MysqlDbConnect) DbInfo() DbConfig {
	return DbConfig{
		DbType:   conf.conf.DbType,
		Host:     conf.conf.Host,
		Port:     conf.conf.Port,
		Username: conf.conf.Username,
		Password: conf.conf.Password,
		Url:      conf.conf.Url,
	}
}

type Sqlite3DbConnect struct {
}

func (conf *Sqlite3DbConnect) Connect() bool {
	return false
}

func (conf *Sqlite3DbConnect) ShowTables() string {
	return "show tables"
}

func (conf *Sqlite3DbConnect) ShowDatabase() string {
	return "show databases"
}

func (conf *Sqlite3DbConnect) DbInfo() DbConfig {
	return DbConfig{}
}
